import mongoose, { Document, Schema } from 'mongoose';

/**
 * 学生信息接口定义
 */
export interface IStudent extends Document {
  studentNo: string;      // 学号（唯一）
  name: string;           // 姓名
  className: string;      // 班级
  grade: number;          // 成绩（0-100）
  email?: string;         // 邮箱
  phone?: string;         // 电话
  gender?: 'male' | 'female' | 'other';  // 性别
  enrollmentDate?: Date;  // 入学日期
  isActive: boolean;      // 是否在读
  createdAt: Date;
  updatedAt: Date;
  // 实例方法
  getGradeLevel(): string;
}

/**
 * 学生信息Schema定义
 */
const StudentSchema: Schema = new Schema(
  {
    studentNo: {
      type: String,
      required: [true, '学号不能为空'],
      unique: true,
      trim: true,
      validate: {
        validator: function(v: string) {
          return /^[0-9]{8,12}$/.test(v);
        },
        message: '学号格式不正确，应为8-12位数字'
      }
    },
    name: {
      type: String,
      required: [true, '姓名不能为空'],
      trim: true,
      minlength: [2, '姓名至少2个字符'],
      maxlength: [50, '姓名最多50个字符']
    },
    className: {
      type: String,
      required: [true, '班级不能为空'],
      trim: true,
      index: true  // 添加索引以优化查询
    },
    grade: {
      type: Number,
      required: [true, '成绩不能为空'],
      min: [0, '成绩不能小于0'],
      max: [100, '成绩不能大于100'],
      validate: {
        validator: Number.isInteger,
        message: '成绩必须为整数'
      }
    },
    email: {
      type: String,
      trim: true,
      lowercase: true,
      validate: {
        validator: function(v: string) {
          if (!v) return true; // 可选字段
          return /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/.test(v);
        },
        message: '邮箱格式不正确'
      }
    },
    phone: {
      type: String,
      trim: true,
      validate: {
        validator: function(v: string) {
          if (!v) return true; // 可选字段
          return /^1[3-9]\d{9}$/.test(v);
        },
        message: '手机号格式不正确'
      }
    },
    gender: {
      type: String,
      enum: {
        values: ['male', 'female', 'other'],
        message: '性别只能是male、female或other'
      }
    },
    enrollmentDate: {
      type: Date,
      default: Date.now
    },
    isActive: {
      type: Boolean,
      default: true
    }
  },
  {
    timestamps: true,  // 自动添加createdAt和updatedAt
    versionKey: false, // 禁用__v字段
    toJSON: {
      transform: function(doc, ret) {
        (ret as any).id = ret._id;
        delete ret._id;
        return ret;
      }
    }
  }
);

/**
 * 添加复合索引以优化查询
 */
StudentSchema.index({ className: 1, grade: -1 });
StudentSchema.index({ name: 'text' });  // 文本搜索索引

/**
 * 实例方法：获取成绩等级
 */
StudentSchema.methods.getGradeLevel = function(): string {
  if (this.grade >= 90) return '优秀';
  if (this.grade >= 80) return '良好';
  if (this.grade >= 60) return '及格';
  return '不及格';
};

/**
 * 静态方法：按班级统计平均分
 */
StudentSchema.statics.getClassAverage = async function(className: string) {
  const result = await this.aggregate([
    { $match: { className, isActive: true } },
    {
      $group: {
        _id: '$className',
        avgGrade: { $avg: '$grade' },
        maxGrade: { $max: '$grade' },
        minGrade: { $min: '$grade' },
        totalStudents: { $sum: 1 }
      }
    }
  ]);
  return result[0] || null;
};

/**
 * 静态方法：获取成绩分布统计
 */
StudentSchema.statics.getGradeDistribution = async function(className?: string) {
  const matchStage = className ? { className, isActive: true } : { isActive: true };
  
  const result = await this.aggregate([
    { $match: matchStage },
    {
      $bucket: {
        groupBy: '$grade',
        boundaries: [0, 60, 80, 90, 100],
        default: 'other',
        output: {
          count: { $sum: 1 },
          students: { $push: { name: '$name', grade: '$grade' } }
        }
      }
    }
  ]);
  
  return {
    excellent: result.find(r => r._id === 90)?.count || 0,   // 90-100
    good: result.find(r => r._id === 80)?.count || 0,        // 80-89
    pass: result.find(r => r._id === 60)?.count || 0,        // 60-79
    fail: result.find(r => r._id === 0)?.count || 0          // 0-59
  };
};

/**
 * 保存前的钩子：自动转换学号为大写（如果需要）
 */
StudentSchema.pre('save', function(next) {
  // 可以在这里添加额外的业务逻辑
  next();
});

/**
 * 导出模型
 */
const Student = mongoose.model<IStudent>('Student', StudentSchema);

export default Student;
